﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using WaterRevenueMS.Componnent.Tools;
using System.Linq.Expressions;
using WaterRevenueMS.Componnent.Common;

namespace WaterRevenueMS.Componnent.Data
{
    public abstract class UnitOfWorkContextBase:IUnitOfWorkContext
    {
        protected abstract DbContext Context { get; }

        public bool IsCommitted { get; set; }

        //public DbContext DbContext { get { return Context; } }

        public int Commit(bool validateOnSaveEnabled = true)
        {
            if (IsCommitted)
            {
                return 0;
            }
            try
            {
                int result = Context.SaveChanges(validateOnSaveEnabled);
                IsCommitted = true;
                return result;
            }
            catch (DbUpdateException e)
            {
                if (e.InnerException != null)
                {
                    SqlException sqlEx = e.InnerException.InnerException as SqlException;
                    string msg = DataHelper.GetSqlExceptionMessage(sqlEx.Number);
                    throw PublicHelper.ThrowDataAccessException("提交数据更新时发生异常：" + msg, sqlEx);
                }
                throw;
            }
        }

        //public void Rollback()
        //{
        //    IsCommitted = false;
        //}

        //public void Dispose()
        //{
        //    if (!IsCommitted)
        //    {
        //        Commit();
        //    }
        //    Context.Dispose();
        //}

        //public DbSet<TEntity> Set<TEntity, TKey>() where TEntity : EntityBase<TKey>
        //{
        //    return Context.Set<TEntity>();
        //}

        //public void RegisterNew<TEntity, TKey>(TEntity entity) where TEntity : EntityBase<TKey>
        //{
        //    EntityState state = Context.Entry(entity).State;
        //    if (state == EntityState.Detached)
        //    {
        //        Context.Entry(entity).State = EntityState.Added;
        //    }
        //    IsCommitted = false;
        //}

        //public void RegisterNew<TEntity, TKey>(IEnumerable<TEntity> entities) where TEntity : EntityBase<TKey>
        //{
        //    try
        //    {
        //        Context.Configuration.AutoDetectChangesEnabled = false;
        //        foreach (TEntity entity in entities)
        //        {
        //            RegisterNew<TEntity, TKey>(entity);
        //        }
        //    }
        //    finally
        //    {
        //        Context.Configuration.AutoDetectChangesEnabled = true;
        //    }
        //}

        //public void RegisterModified<TEntity, TKey>(TEntity entity) where TEntity : EntityBase<TKey>
        //{
        //    Context.Update<TEntity, TKey>(entity);
        //    IsCommitted = false;
        //}

        //public void RegisterModified<TEntity, TKey>(Expression<Func<TEntity, object>> propertyExpression, TEntity entity) where TEntity : EntityBase<TKey>
        //{
        //    Context.Update<TEntity, TKey>(propertyExpression, entity);
        //    IsCommitted = false;
        //}

        //public void RegisterDeleted<TEntity, TKey>(TEntity entity) where TEntity : EntityBase<TKey>
        //{
        //    Context.Entry(entity).State = EntityState.Deleted;
        //    IsCommitted = false;
        //}

        //public void RegisterDeleted<TEntity, TKey>(IEnumerable<TEntity> entities) where TEntity : EntityBase<TKey>
        //{
        //    try
        //    {
        //        Context.Configuration.AutoDetectChangesEnabled = false;
        //        foreach (TEntity entity in entities)
        //        {
        //            RegisterDeleted<TEntity, TKey>(entity);
        //        }
        //    }
        //    finally
        //    {
        //        Context.Configuration.AutoDetectChangesEnabled = true;
        //    }
        //}
        public void Rollback()
        {
            IsCommitted = false;
        }

        public void Dispose()
        {
            if (!IsCommitted)
            {
                Commit();
            }
            Context.Dispose();
        }

        /// <summary>
        ///   为指定的类型返回 System.Data.Entity.DbSet，这将允许对上下文中的给定实体执行 CRUD 操作。
        /// </summary>
        /// <typeparam name="TEntity"> 应为其返回一个集的实体类型。 </typeparam>
        /// <returns> 给定实体类型的 System.Data.Entity.DbSet 实例。 </returns>
        public DbSet<TEntity> Set<TEntity, TKey>() where TEntity : EntityBase<TKey>
        {
            return Context.Set<TEntity>();
        }

        /// <summary>
        ///     注册一个新的对象到仓储上下文中
        /// </summary>
        /// <typeparam name="TEntity"> 要注册的类型 </typeparam>
        /// <param name="entity"> 要注册的对象 </param>
        public void RegisterNew<TEntity, TKey>(TEntity entity) where TEntity : EntityBase<TKey>
        {
            EntityState state = Context.Entry(entity).State;
            if (state == EntityState.Detached)
            {
                Context.Entry(entity).State = EntityState.Added;
            }
            IsCommitted = false;
        }

        /// <summary>
        ///     批量注册多个新的对象到仓储上下文中
        /// </summary>
        /// <typeparam name="TEntity"> 要注册的类型 </typeparam>
        /// <param name="entities"> 要注册的对象集合 </param>
        public void RegisterNew<TEntity, TKey>(IEnumerable<TEntity> entities) where TEntity : EntityBase<TKey>
        {
            try
            {
                Context.Configuration.AutoDetectChangesEnabled = false;
                foreach (TEntity entity in entities)
                {
                    RegisterNew<TEntity,TKey>(entity);
                }
            }
            finally
            {
                Context.Configuration.AutoDetectChangesEnabled = true;
            }
        }

        /// <summary>
        ///     注册一个更改的对象到仓储上下文中
        /// </summary>
        /// <typeparam name="TEntity"> 要注册的类型 </typeparam>
        /// <param name="entity"> 要注册的对象 </param>
        public void RegisterModified<TEntity, TKey>(TEntity entity) where TEntity : EntityBase<TKey>
        {
            if (Context.Entry(entity).State == EntityState.Detached)
            {
                Context.Set<TEntity>().Attach(entity);
            }
            Context.Entry(entity).State = EntityState.Modified;
            IsCommitted = false;
        }

        public void RegisterModified<TEntity, TKey>(Expression<Func<TEntity, object>> propertyExpression, TEntity entity) where TEntity : EntityBase<TKey>
        {
            Context.Update<TEntity, TKey>(propertyExpression, entity);
            IsCommitted = false;
        }

        /// <summary>
        ///   注册一个删除的对象到仓储上下文中
        /// </summary>
        /// <typeparam name="TEntity"> 要注册的类型 </typeparam>
        /// <param name="entity"> 要注册的对象 </param>
        public void RegisterDeleted<TEntity,TKey>(TEntity entity) where TEntity : EntityBase<TKey>
        {
            Context.Entry(entity).State = EntityState.Deleted;
            IsCommitted = false;
        }

        /// <summary>
        ///   批量注册多个删除的对象到仓储上下文中
        /// </summary>
        /// <typeparam name="TEntity"> 要注册的类型 </typeparam>
        /// <param name="entities"> 要注册的对象集合 </param>
        public void RegisterDeleted<TEntity,TKey>(IEnumerable<TEntity> entities) where TEntity : EntityBase<TKey>
        {
            try
            {
                Context.Configuration.AutoDetectChangesEnabled = false;
                foreach (TEntity entity in entities)
                {
                    RegisterDeleted<TEntity,TKey>(entity);
                }
            }
            finally
            {
                Context.Configuration.AutoDetectChangesEnabled = true;
            }
        }
    }
}
